package com.example.demo.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.order.cache.CartCacheService;
import com.example.demo.order.dto.request.*;
import com.example.demo.order.dto.response.CartResponse;
import com.example.demo.order.dto.response.OrderResponse;
import com.example.demo.order.entity.Cart;
import com.example.demo.order.exception.BusinessException;
import com.example.demo.order.lock.DistributedLockUtil;
import com.example.demo.order.mapper.CartMapper;
import com.example.demo.order.security.AuthenticationUtil;
import com.example.demo.order.security.OrderSecurityUtil;
import com.example.demo.order.security.RateLimitUtil;
import com.example.demo.order.service.CartService;
import com.example.demo.order.service.OrderService;
import com.example.demo.order.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @ClassName CartServiceImpl
 * @Description 购物车服务实现类 - 按用户隔离模式
 * <p>
 * 安全特性：
 * 1. 所有操作都基于当前登录用户（从Session获取，不信任前端传参）
 * 2. 用户只能操作自己的购物车，无法访问他人数据
 * 3. 用户级别的分布式锁，提升并发性能
 * 4. 用户级别的缓存key，互不影响
 * </p>
 * @Author MingChang.Wei
 * @Date 2025/9/26
 * @Modified 2025/10/28 - 重构为按用户隔离模式
 **/
@Slf4j
@Service
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements CartService {
    
    @Resource
    private OrderService orderService;
    
    @Resource
    private CartCacheService cartCacheService;
    
    @Resource
    private DistributedLockUtil distributedLockUtil;
    
    @Resource
    private OrderSecurityUtil orderSecurityUtil;
    
    @Resource
    private RateLimitUtil rateLimitUtil;
    
    @Resource
    private ProductService productService;
    
    @Resource
    private AuthenticationUtil authenticationUtil;
    
    // 移除统一购物车的key，改为用户级别
    // private static final String UNIFIED_CACHE_KEY = "unified_cart";
    // private static final String UNIFIED_LOCK_KEY = "unified_cart_lock";
    
    /**
     * 获取用户级别的缓存key
     */
    private String getUserCacheKey(String username) {
        return "cart:user:" + username;
    }
    
    /**
     * 获取用户级别的锁key
     */
    private String getUserLockKey(String username) {
        return "cart:lock:user:" + username;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public Boolean addToCart(CartAddRequest request) {
        // 获取当前登录用户（安全：从Session获取，不信任前端传参）
        String currentUsername = authenticationUtil.getCurrentUsername();
        
        // 参数校验
        orderSecurityUtil.validateQuantity(request.getQuantity());
        
        // 用户级别的锁和缓存key
        String userLockKey = getUserLockKey(currentUsername);
        String userCacheKey = getUserCacheKey(currentUsername);
        String lockValue = UUID.randomUUID().toString();
        
        try {
            // 获取用户级别的分布式锁（不同用户可并发操作）
            if (distributedLockUtil.tryLock(userLockKey, lockValue, 5000)) {
                // 检查当前用户的购物车商品数量限制
                long userCartCount = lambdaQuery()
                        .eq(Cart::getCreateBy, currentUsername)
                        .count();
                if (userCartCount >= 100) { // 单个用户购物车商品数限制
                    throw new BusinessException("您的购物车商品数量已达上限（100个）");
                }
                
                // 检查当前用户是否已存在相同商品
                Cart existingCart = lambdaQuery()
                        .eq(Cart::getCreateBy, currentUsername)
                        .eq(Cart::getProductId, request.getProductId())
                        .one();
                        
                if (existingCart != null) {
                    // 更新数量
                    int newQuantity = existingCart.getQuantity() + request.getQuantity();
                    if (newQuantity > 999) {
                        throw new BusinessException("单个商品数量不能超过999");
                    }
                    existingCart.setQuantity(newQuantity);
                    existingCart.setUpdateBy(currentUsername);
                    boolean updateResult = updateById(existingCart);
                    
                    if (updateResult) {
                        // 清除用户缓存
                        cartCacheService.clearCartCache(userCacheKey);
                        log.info("购物车商品数量更新成功: user={}, productId={}, newQuantity={}", 
                                currentUsername, request.getProductId(), newQuantity);
                        return true;
                    }
                } else {
                    // 新增商品到购物车
                    Cart cart = createNewCartItem(request, currentUsername);
                    boolean saveResult = save(cart);
                    
                    if (saveResult) {
                        // 清除用户缓存
                        cartCacheService.clearCartCache(userCacheKey);
                        log.info("新商品添加到购物车成功: user={}, productId={}, quantity={}", 
                                currentUsername, request.getProductId(), request.getQuantity());
                        return true;
                    }
                }
                
                throw new BusinessException("添加购物车失败");
            } else {
                throw new BusinessException("系统繁忙，请稍后重试");
            }
        } finally {
            distributedLockUtil.releaseLock(userLockKey, lockValue);
        }
    }
    
    /**
     * 创建新的购物车商品
     */
    private Cart createNewCartItem(CartAddRequest request, String username) {
        Cart cart = new Cart();
        cart.setProductId(request.getProductId());
        cart.setQuantity(request.getQuantity());
        cart.setCreateBy(username);
        cart.setUpdateBy(username);
        cart.setSelected(true);
        
        // 从商品服务获取商品信息
        try {
            // 验证商品是否存在
            if (!productService.isProductExists(request.getProductId())) {
                throw new BusinessException("商品不存在");
            }
            
            cart.setProductName(productService.getProductName(request.getProductId()));
            cart.setPrice(productService.getProductPrice(request.getProductId()));
            cart.setImageUrl(productService.getProductImageUrl(request.getProductId()));
            cart.setSku(productService.getProductSku(request.getProductId()));
        } catch (Exception e) {
            log.error("获取商品信息失败: productId={}", request.getProductId(), e);
            throw new BusinessException("商品信息获取失败: " + e.getMessage());
        }
        
        return cart;
    }
    
    @Override
    public Page<CartResponse> getCartList(Integer current, Integer size) {
        // 获取当前登录用户
        String currentUsername = authenticationUtil.getCurrentUsername();
        String userCacheKey = getUserCacheKey(currentUsername);
        
        Page<Cart> page = new Page<>(current, size);
        
        // 先尝试从缓存获取
        List<Cart> cachedList = cartCacheService.getCachedCartList(userCacheKey);
        if (cachedList != null && !cachedList.isEmpty()) {
            log.info("购物车缓存命中: user={}, size={}", currentUsername, cachedList.size());
            return buildCartResponsePage(cachedList, current, size);
        }
        
        // 从数据库查询（关键：只查询当前用户的购物车）
        Page<Cart> cartPage = page(page, new LambdaQueryWrapper<Cart>()
                .eq(Cart::getCreateBy, currentUsername)  // 用户过滤
                .orderByDesc(Cart::getCreateTime));
        
        if (cartPage.getRecords() != null && !cartPage.getRecords().isEmpty()) {
            cartCacheService.cacheCartList(userCacheKey, cartPage.getRecords());
        }
        
        // 转换为响应对象
        Page<CartResponse> responsePage = new Page<>(current, size);
        responsePage.setTotal(cartPage.getTotal());
        responsePage.setRecords(cartPage.getRecords().stream()
                .map(this::convertToCartResponse)
                .collect(Collectors.toList()));
        
        log.info("查询用户购物车: user={}, total={}", currentUsername, cartPage.getTotal());
        return responsePage;
    }
    
    /**
     * 构建购物车响应分页对象
     */
    private Page<CartResponse> buildCartResponsePage(List<Cart> cartList, Integer current, Integer size) {
        Page<CartResponse> responsePage = new Page<>(current, size);
        
        // 手动分页
        int start = (current - 1) * size;
        int end = Math.min(start + size, cartList.size());
        
        List<CartResponse> pageRecords = cartList.subList(start, end).stream()
                .map(this::convertToCartResponse)
                .collect(Collectors.toList());
        
        responsePage.setTotal(cartList.size());
        responsePage.setRecords(pageRecords);
        
        return responsePage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCartQuantity(CartUpdateRequest request) {
        // 获取当前登录用户
        String currentUsername = authenticationUtil.getCurrentUsername();
        String userCacheKey = getUserCacheKey(currentUsername);
        
        // 参数校验
        orderSecurityUtil.validateQuantity(request.getQuantity());
        
        // 先查询购物车项，验证所属权限
        Cart cart = getById(request.getCartId());
        if (cart == null) {
            throw new BusinessException("购物车商品不存在");
        }
        
        // 权限验证：只能更新自己的购物车
        if (!currentUsername.equals(cart.getCreateBy())) {
            log.warn("用户尝试更新他人购物车: user={}, cartOwner={}, cartId={}", 
                    currentUsername, cart.getCreateBy(), request.getCartId());
            throw new BusinessException("无权操作他人的购物车");
        }
        
        // 更新数量
        boolean updateResult = lambdaUpdate()
                .eq(Cart::getId, request.getCartId())
                .eq(Cart::getCreateBy, currentUsername)  // 双重验证
                .set(Cart::getQuantity, request.getQuantity())
                .set(Cart::getUpdateBy, currentUsername)
                .update();
        
        if (updateResult) {
            // 清除用户缓存
            cartCacheService.clearCartCache(userCacheKey);
            log.info("购物车商品数量更新成功: user={}, cartId={}, newQuantity={}", 
                    currentUsername, request.getCartId(), request.getQuantity());
        }
        
        return updateResult;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeFromCart(Long cartId) {
        // 获取当前登录用户
        String currentUsername = authenticationUtil.getCurrentUsername();
        String userCacheKey = getUserCacheKey(currentUsername);
        
        // 先查询购物车项，验证所属权限
        Cart cart = getById(cartId);
        if (cart == null) {
            throw new BusinessException("购物车商品不存在");
        }
        
        // 权限验证：只能删除自己的购物车
        if (!currentUsername.equals(cart.getCreateBy())) {
            log.warn("用户尝试删除他人购物车: user={}, cartOwner={}, cartId={}", 
                    currentUsername, cart.getCreateBy(), cartId);
            throw new BusinessException("无权操作他人的购物车");
        }
        
        // 删除购物车项
        boolean removeResult = lambdaUpdate()
                .eq(Cart::getId, cartId)
                .eq(Cart::getCreateBy, currentUsername)  // 双重验证
                .remove();
        
        if (removeResult) {
            // 清除用户缓存
            cartCacheService.clearCartCache(userCacheKey);
            log.info("购物车商品删除成功: user={}, cartId={}", currentUsername, cartId);
        }
        
        return removeResult;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchRemoveFromCart(List<Long> cartIds, String username) {
        // 获取当前登录用户（不信任传参中的username）
        String currentUsername = authenticationUtil.getCurrentUsername();
        String userCacheKey = getUserCacheKey(currentUsername);
        
        if (cartIds == null || cartIds.isEmpty()) {
            throw new BusinessException("购物车ID列表不能为空");
        }
        
        // 验证所有购物车项都属于当前用户
        long count = lambdaQuery()
                .in(Cart::getId, cartIds)
                .eq(Cart::getCreateBy, currentUsername)
                .count();
        
        if (count != cartIds.size()) {
            log.warn("批量删除包含非本人购物车: user={}, requestIds={}, ownedCount={}", 
                    currentUsername, cartIds.size(), count);
            throw new BusinessException("包含无权操作的购物车商品");
        }
        
        // 批量删除（只删除属于当前用户的）
        boolean removeResult = lambdaUpdate()
                .in(Cart::getId, cartIds)
                .eq(Cart::getCreateBy, currentUsername)  // 安全验证
                .remove();
        
        if (removeResult) {
            // 清除用户缓存
            cartCacheService.clearCartCache(userCacheKey);
            log.info("批量删除购物车商品成功: user={}, count={}", currentUsername, cartIds.size());
        }
        
        return removeResult;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED, timeout = 30)
    public List<OrderResponse> checkoutCart(CartCheckoutRequest request) {
        // 获取当前登录用户（不信任前端传参）
        String currentUsername = authenticationUtil.getCurrentUsername();
        String userLockKey = getUserLockKey(currentUsername);
        String userCacheKey = getUserCacheKey(currentUsername);
        
        // TODO: 限流检查（需要适配String username版本）
        // rateLimitUtil.checkOrderCreateLimit(currentUsername);
        
        // 用户级别的分布式锁防止重复结算
        String lockValue = UUID.randomUUID().toString();
        
        try {
            if (distributedLockUtil.tryLock(userLockKey, lockValue, 10000)) {
                // TODO: 记录敏感操作（需要适配String username版本）
                // orderSecurityUtil.logSensitiveOperation("CART_CHECKOUT", currentUsername, request);
                
                // 查询选中的购物车商品（只查询属于当前用户的）
                List<Cart> selectedCarts = lambdaQuery()
                        .in(Cart::getId, request.getCartIds())
                        .eq(Cart::getCreateBy, currentUsername)  // 安全：只查询自己的
                        .eq(Cart::getSelected, true)
                        .list();
                
                if (selectedCarts.isEmpty()) {
                    throw new BusinessException("没有选中的商品或商品不存在");
                }
                
                // 验证查询到的数量是否匹配（防止包含他人的购物车项）
                if (selectedCarts.size() != request.getCartIds().size()) {
                    log.warn("购物车结算包含非本人商品: user={}, requestCount={}, actualCount={}", 
                            currentUsername, request.getCartIds().size(), selectedCarts.size());
                    throw new BusinessException("部分商品不存在或无权操作");
                }
                
                // 创建订单
                List<OrderResponse> orderResponses = new ArrayList<>();
                for (Cart cartItem : selectedCarts) {
                    try {
                        // 创建订单请求
                        OrderCreateRequest orderRequest = new OrderCreateRequest();
                        orderRequest.setUsername(currentUsername);  // 使用当前登录用户
                        orderRequest.setProductId(cartItem.getProductId());
                        orderRequest.setQuantity(cartItem.getQuantity());
                        
                        // 创建订单
                        OrderResponse orderResponse = orderService.createOrder(orderRequest);
                        orderResponses.add(orderResponse);
                        
                        log.info("订单创建成功: user={}, orderNo={}, productId={}, amount={}", 
                                currentUsername, orderResponse.getOrderNo(), 
                                cartItem.getProductId(), orderResponse.getTotalAmount());
                    } catch (Exception e) {
                        log.error("订单创建失败: user={}, productId={}", 
                                 currentUsername, cartItem.getProductId(), e);
                        throw new BusinessException("订单创建失败: " + e.getMessage());
                    }
                }
                
                // 删除已结算的购物车商品
                boolean removeResult = batchRemoveFromCart(request.getCartIds(), currentUsername);
                if (!removeResult) {
                    log.warn("购物车商品删除失败，但订单已创建: user={}", currentUsername);
                }
                
                // 清除用户缓存
                cartCacheService.clearCartCache(userCacheKey);
                
                log.info("购物车结算完成: user={}, orderCount={}", currentUsername, orderResponses.size());
                return orderResponses;
            } else {
                throw new BusinessException("系统繁忙，请稍后重试");
            }
        } finally {
            distributedLockUtil.releaseLock(userLockKey, lockValue);
        }
    }
    
    /**
     * 转换为购物车响应对象
     */
    private CartResponse convertToCartResponse(Cart cart) {
        CartResponse response = new CartResponse();
        BeanUtils.copyProperties(cart, response);
        return response;
    }
    
    /**
     * 异步清理过期购物车商品
     */
    @Async
    public void cleanExpiredCartItems() {
        try {
            // 删除30天前的购物车商品
            LocalDateTime expireTime = LocalDateTime.now().minusDays(30);
            
            // 先查询要删除的购物车，获取涉及的用户
            List<Cart> expiredCarts = lambdaQuery()
                    .lt(Cart::getCreateTime, expireTime)
                    .select(Cart::getCreateBy)
                    .list();
            
            if (expiredCarts.isEmpty()) {
                log.info("没有需要清理的过期购物车商品");
                return;
            }
            
            // 收集涉及的用户
            Set<String> affectedUsers = expiredCarts.stream()
                    .map(Cart::getCreateBy)
                    .collect(Collectors.toSet());
            
            // 删除过期购物车
            boolean removed = lambdaUpdate()
                    .lt(Cart::getCreateTime, expireTime)
                    .remove();
            
            if (removed) {
                // 清除所有受影响用户的缓存
                affectedUsers.forEach(username -> {
                    String userCacheKey = getUserCacheKey(username);
                    cartCacheService.clearCartCache(userCacheKey);
                });
                
                log.info("清理过期购物车商品成功: 删除数量={}, 影响用户数={}", 
                        expiredCarts.size(), affectedUsers.size());
            }
        } catch (Exception e) {
            log.error("清理过期购物车商品失败", e);
        }
    }
}